<?php
declare(strict_types=1);
namespace app\admin\model;
use aphp\core\Model;

class Category extends Model
{
	protected string $table = 'category';
	protected string $pk = 'id';

	protected array $validate = [
        ['pid', 'required', '请选择上级栏目', IF_MUST, AC_BOTH],
        ['title', 'chs_alpha_num', '名称应为汉字字母数字', IF_MUST, AC_BOTH],
        ['sign', 'string|unique', '标识格式错误|标识已存在', IF_MUST, AC_BOTH],
		['sort', 'number', '排序必须是数字', IF_ISSET, AC_BOTH],
	];

	protected array $auto = [
		['status', '1', 'string', IF_MUST, AC_INSERT],
	];

    // 新增之前
    protected function _before_insert(array &$data): void
    {
        if ($data['type_id'] == 2 && $data['model_id'] == 0) {
            $this->errors[] = '类型为列表时必须选择所属模型';
            return;
        }
        $parent = $this->db->field('id,level,path')->where('id', $data['pid'])->find();
        if (!$parent) {
            $this->errors[] = '上级栏目不存在';
            return;
        }
        $data['level'] = $parent['level'] + 1; // 层次
        $data['path'] = $parent['path'].$parent['id'].','; // 路径
    }

    // 新增之后
    protected function _after_insert(array $data): void
    {
        $this->db->where('id', $data['pid'])->setInc('sub_count'); // 子统计
        $this->db->where('id', 'in', trim($data['path'], ','))->setInc('tree_count'); // 树统计
    }

    // 修改之前
    protected function _before_update(array &$data): void
    {
        if ($data['type_id'] == 2 && $data['model_id'] == 0) {
            $this->errors[] = '类型为列表时必须选择所属模型';
            return;
        }
        if ($data['pid'] != $this->data['pid']) {
            if ($data['pid'] == $data['id']) {
                $this->errors[] = '上级栏目不能是自己';
                return;
            }
            $parent = $this->db->field('id,level,path')->where('id', $data['pid'])->find();
            if (!$parent) {
                $this->errors[] = '上级栏目不存在';
                return;
            }
            if (str_contains($parent['path'], ','.$data['id'].',')) {
                $this->errors[] = '上级栏目不能是自己的子栏目';
                return;
            }
            $data['level'] = $parent['level'] + 1; // 层次
            $data['path'] = $parent['path'].$parent['id'].','; // 路径
        }
    }

    // 修改之后
    protected function _after_update(array $before, array $after): void
    {
        if ($before['pid'] != $after['pid']) {
            // 更新原来的
            $this->db->where('id', $before['pid'])->setDec('sub_count'); // 更新子统计
            $this->db->where('id', 'in', trim($before['path'], ','))->setDec('tree_count', $before['tree_count'] + 1); // 更新树统计
            // 更新现在的
            $this->db->where('id', $after['pid'])->setInc('sub_count'); // 更新子统计
            $this->db->where('id', 'in', trim($after['path'], ','))->setInc('tree_count', $after['tree_count'] + 1); // 更新树统计
            // 更新伞下的
            if ($after['level'] > $before['level']) {
                // 现在层级大于原先层级
                $this->db->where('path', 'like', '%,'.$after['id'].',%')->setInc('level', $after['level'] - $before['level']); // 更新层级
            } elseif ($after['level'] < $before['level']) {
                // 现在层级小于原先层级
                $this->db->where('path', 'like', '%,'.$after['id'].',%')->setDec('level', $before['level'] - $after['level']); // 更新层级
            }
            if ($after['path'] != $before['path']) {
                // 更新路径
                $list = $this->db->where('path', 'like', '%,'.$after['id'].',%')->field('id,path')->select();
                foreach ($list as $vo) {
                    $this->db->where('id', $vo['id'])->setField('path', str_replace($before['path'], $after['path'], $vo['path']));
                }
            }
        }
    }

    // 删除之前
    protected function _before_delete(array $data): void
    {
        $this->db = $this->db->where('id>2'); // 禁止删除根目录
    }

    // 删除之后
    protected function _after_delete(array $data): void
    {
        $this->db->where('id', $data['pid'])->setDec('sub_count'); // 更新子统计
        if ($data['tree_count'] > 0) {
            $this->db->where('path', 'like', '%,'.$data['id'].',%')->delete(); // 删除伞下
        }
        $this->db->where('id', 'in', trim($data['path'], ','))->setDec('tree_count', $data['tree_count'] + 1); // 更新树统计
    }

}